package com.sdkj.fixed.asset.system.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.sdkj.fixed.asset.api.system.in_vo.BindAuthParamEntity;
import com.sdkj.fixed.asset.api.system.in_vo.RoleBindUser;
import com.sdkj.fixed.asset.api.system.out_vo.AuthTreeResultEntity;
import com.sdkj.fixed.asset.common.base.BaseMapper;
import com.sdkj.fixed.asset.common.base.BaseService;
import com.sdkj.fixed.asset.common.core.RoleType;
import com.sdkj.fixed.asset.common.exception.LogicException;
import com.sdkj.fixed.asset.pojo.system.RoleAndMenu;
import com.sdkj.fixed.asset.pojo.system.RoleAndUser;
import com.sdkj.fixed.asset.pojo.system.RoleManagement;
import com.sdkj.fixed.asset.pojo.system.UserManagement;
import com.sdkj.fixed.asset.system.mapper.RoleAndMenuMapper;
import com.sdkj.fixed.asset.system.mapper.RoleAndUserMapper;
import com.sdkj.fixed.asset.system.mapper.RoleManagementMapper;
import com.sdkj.fixed.asset.system.mapper.UserManagementMapper;
import com.sdkj.fixed.asset.system.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName RoleService
 * @Description TODO
 * @Author 张欣
 * @Date 2020/7/21 14:39
 */
@Service
public class RoleService extends BaseService<RoleManagement> {
    @Autowired
    private RoleManagementMapper roleManagementMapper;
    @Autowired
    private RoleAndUserMapper roleAndUserMapper;
    @Autowired
    private RoleAndMenuMapper roleAndMenuMapper;
    @Autowired
    private UserManagementMapper userManagementMapper;
    @Autowired
    private RedisUtil redisUtil;
    @Override
    public BaseMapper getMapper() {
        return roleManagementMapper;
    }
    public void addRole(RoleManagement roleManagement){

        roleManagement.setState(1);
        roleManagement.setCtime(DateUtil.now());
        roleManagement.setEtime(DateUtil.now());
        roleManagementMapper.insertSelective(roleManagement);
    }
    public void editRole(RoleManagement roleManagement){
        RoleManagement role = roleManagementMapper.selectByPrimaryKey(roleManagement.getId());
        if(role == null || role.getState() == 2){
            throw new LogicException("角色不存在");
        }
        role.setComments(roleManagement.getComments());
        role.setName(roleManagement.getName());
        role.setEtime(DateUtil.now());
        roleManagementMapper.updateByPrimaryKey(role);
    }
    /**
     * 分配用户
     * @param roleBindUser
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void bindUser(RoleBindUser roleBindUser){
        //先删除所有
        Example example = new Example(RoleAndUser.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("roleId",roleBindUser.getRoleId());
        List<RoleAndUser> roleAndUsers = roleAndUserMapper.selectByExample(example);
        List<String> hasUser = roleAndUsers.stream().map(RoleAndUser::getUserId).collect(Collectors.toList());
        for(RoleAndUser entity : roleAndUsers){
            roleAndUserMapper.delete(entity);
        }
        if(roleBindUser.getUserIds() != null){
            String roleId = roleBindUser.getRoleId();
            for(String userId : roleBindUser.getUserIds()){
                RoleAndUser entity = new RoleAndUser();
                entity.setRoleId(roleId);
                entity.setUserId(userId);
                roleAndUserMapper.insertSelective(entity);
            }
        }
        hasUser.removeAll(roleBindUser.getUserIds());
        for(String userId : hasUser){
            redisUtil.del("PC_"+userId);
        }
    }

    /**
     * 查询绑定角色人员且为启用状态人员
     * @param roleId
     * @return
     */
    public RoleBindUser  queryHasBindUser( RoleManagement roleId){
        Example example = new Example(RoleAndUser.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("roleId",roleId.getId());
        List<RoleAndUser> roleAndUsers = roleAndUserMapper.selectByExample(example);
        List<String> userIds = roleAndUsers.stream().map(RoleAndUser::getUserId).collect(Collectors.toList());
        if(userIds.size()>0){
            Example example2 = new Example(UserManagement.class);
            Example.Criteria criteria2 = example2.createCriteria();
            criteria2.andIn("id",userIds);
            criteria2.andEqualTo("state",1);
            criteria2.andEqualTo("type",1);
            List<UserManagement> userManagements = userManagementMapper.selectByExample(example2);
            userIds = userManagements.stream().map(UserManagement::getId).collect(Collectors.toList());
        }

        RoleBindUser result = new RoleBindUser();
        result.setUserIds(userIds);
        result.setRoleId(roleId.getId());
        return result;
    }
    /**
     * 查询权限树
     * @param roleId
     * @return
     */
    public List<AuthTreeResultEntity> getAuthTree(String roleId,boolean isAdmin){
        RoleManagement roleManage = roleManagementMapper.selectByPrimaryKey(roleId);
        if(roleManage == null){
            throw new LogicException("角色不存在");
        }
        //菜单

        return   getMenuTree(roleManage ,isAdmin);

    }
    /**
     * 查询菜单树
     * @param
     * @return
     */
    private List<AuthTreeResultEntity> getMenuTree( RoleManagement roleManage,boolean isAdmin){
        //超级管理员登录，且为园区管理员
        if(isAdmin && roleManage.getLevel().equals(RoleType.ADMIN.getRoleType()) ){
            return roleManagementMapper.getAllMenu(roleManage.getId());
        }else{
            List<AuthTreeResultEntity>  authMenus = roleManagementMapper.getAuthMenu(roleManage.getId(),roleManage.getOrgId());
            //园区角色与机构角色在sql里区别
            Set<String> parentIds = new LinkedHashSet<>();
            //查询父节点是否包含在内
            for (AuthTreeResultEntity menu : authMenus){
                String allParentId = roleManagementMapper.getAllParentId(menu.getAuthId());
                if(StrUtil.isNotBlank(allParentId)){
                    for(String str : allParentId.split(",")){
                        parentIds.add(str);
                    }
                }

            }
            Set<String> ids = authMenus.stream().map(AuthTreeResultEntity::getAuthId).collect(Collectors.toSet());
            parentIds.removeAll(ids);
            //查询父机构信息
            if(parentIds.size() > 0){
                List<AuthTreeResultEntity> menusByMenuId = roleManagementMapper.getMenusByMenuId(parentIds);
                authMenus.addAll(menusByMenuId)  ;
            }
            Comparator<AuthTreeResultEntity> netTypeComparator = new Comparator<AuthTreeResultEntity>() {
                @Override
                public int compare(AuthTreeResultEntity o1, AuthTreeResultEntity o2) {
                    if(o1.getSort() == null){
                        o1.setSort(1);
                    }
                    if(o2.getSort() == null){
                        o2.setSort(1);
                    }
                    if (o1.getSort() > o2.getSort() ){
                        return 1;
                    }
                    if (o1.getSort().equals(o2.getSort())) {
                        return 0;
                    }
                    return -1;
                }
            };

            Collections.sort(authMenus,netTypeComparator);
            return authMenus;
        }
    }
    /**
     * 绑定权限
     * @param roleAuth
     */
    @Transactional(rollbackFor = Exception.class)
    public void bindAuth(BindAuthParamEntity roleAuth, String userId){
        //角色id
        String roleId = roleAuth.getRoleId();
        RoleManagement role = roleManagementMapper.selectByPrimaryKey(roleId);
        if(role == null){
            throw new LogicException("角色不存在");
        }

        //先删除所有权限
        //菜单权限
        deleteRoleBindMenu(roleId,role.getLevel(),roleAuth.getMenus(),role.getOrgId());

        insertBindMenu(roleAuth.getMenus(),roleId);
    }
    //删除角色菜单绑定
    private void deleteRoleBindMenu(String roleId,String level,List newMenu,String orgId){
        Example example = new Example(RoleAndMenu.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("roleId",roleId);
        List<RoleAndMenu> menus =  roleAndMenuMapper.selectByExample(example);
        if(menus.size() == 0 ){
            return;
        } //如果是园区管理员，判断取消的权限中是否有其他角色在使用
        if(RoleType.ADMIN.getRoleType().equals(level)){
            List<String> hasMenu = menus.stream().map(RoleAndMenu::getAuthId).collect(Collectors.toList());
            hasMenu.removeAll(newMenu);
            if(hasMenu.size() > 0){
                //查询其他角色是否使用
                Map<String,Object> param = new HashMap();
                param.put("orgIf",orgId);
                param.put("hasMenu",hasMenu);
                param.put("roleId",roleId);
                List<String> noParkAdminBindAuth = roleAndMenuMapper.getNoParkAdminBindAuth(param);
                if(noParkAdminBindAuth.size()>0){
                    throw new LogicException("取消的菜单中有其他角色在使用，请先解除其他角色的菜单绑定");
                }
            }
        }
        for( RoleAndMenu menu : menus ){
            roleAndMenuMapper.delete(menu);
        }
    }
    //绑定菜单
    private void insertBindMenu(List<String> menus,String roleId){
        if(menus != null){
            RoleAndMenu entity = null;
            for( String menuId : menus ){
                entity = new RoleAndMenu();
                entity.setAuthId(menuId);
                entity.setRoleId(roleId);
                roleAndMenuMapper.insertSelective(entity);
            }
        }

    }
}
